package com.kang.handler;

import com.alibaba.fastjson.JSONObject;
import com.kang.base.LoginDataBase;
import com.kang.entity.SysMenu;
import com.kang.util.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 2. 从AuthenticationToken读取Token并做用户数据解析
 */
@Slf4j
@Component
public class ScAuthenticationManager implements ReactiveAuthenticationManager {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        String tokenString = (String) authentication.getPrincipal();
        //校验token
        LoginUser loginUser = parseToken(tokenString);

        return Mono.just(authentication).map(auth -> {
            return new UsernamePasswordAuthenticationToken(loginUser, null, null);
        });
    }

    /**
     * 校验token
     *
     * @param tokenString
     * @return
     */
    private LoginUser parseToken(String tokenString) {
        try {
            String token = stringRedisTemplate.opsForValue().get("login:token:" + tokenString);
            if (StringUtils.isEmpty(token)) {
                return null;
            }
            // 刷新token有效期
            stringRedisTemplate.expire("login:token:" + tokenString,30, TimeUnit.MINUTES);
//            String loginJsonString = stringRedisTemplate.opsForValue().get("login:token:" + tokenString);
            LoginDataBase loginDataBase = JSONObject.parseObject(token, LoginDataBase.class);
            return new LoginUser(loginDataBase.getUser(),loginDataBase.getMenuList() == null ? null :loginDataBase.getMenuList().stream().map(SysMenu::getPerms).collect(Collectors.toList()));
        } catch (Exception exception) {
            log.info("token转换获取异常",exception);
            return null;
        }
    }
}
